// 用于存储Socket.IO服务器实例和在线用户
let ioInstance = null;
const onlineUsers = new Map();
const jwt = require("jsonwebtoken");
const accessTokenSecret = "abc123";
const { User } = require("../Config/sqliteDB"); // 导入User模型

// 修改初始化Socket.IO服务器部分
function initSocketIO(server) {
  if (ioInstance) return ioInstance;

  const { Server } = require("socket.io");
  ioInstance = new Server(server, {
    cors: {
      // 为了测试，暂时允许所有源
      origin: "*",
      methods: ["GET", "POST"],
      credentials: true,
      allowedHeaders: ["*"],
    },
    // 增加pingTimeout，减少误判断
    pingTimeout: 60000, // 增加到60秒
    pingInterval: 25000, // 增加到25秒
    transports: ["websocket", "polling"],
  });

  // 添加调试日志
  ioInstance.on("connection_error", (error) => {
    console.error("Socket.IO连接错误详情:");
    console.error("- 错误消息:", error.message);
    console.error("- 错误代码:", error.code);
    console.error("- 错误上下文:", error.context);
    console.error("- 传输错误:", error.transportError);
  });

  setupSocketEvents(ioInstance);
  return ioInstance;
}

// 设置Socket.IO事件处理
function setupSocketEvents(io) {
  io.on("connection", async (socket) => {
    console.log(`新用户连接：socketID=${socket.id}`);
    
    // 从查询参数获取JWT token
    const token = socket.handshake.query.token;

    console.log(
      "获取到的Token:",
      token ? "存在，长度=" + token.length : "不存在"
    );

    if (!token) {
      console.log("未提供认证token，连接被拒绝");
      socket.disconnect();
      return;
    }

    // 在connection事件的认证部分
    try {
      // 使用与auth.js相同的密钥验证token
      const decoded = jwt.verify(token, accessTokenSecret);

      // 绑定用户信息到socket
      socket.userId = decoded.id.toString(); // 确保是字符串类型
      socket.userName = decoded.username;

      console.log(`Token验证成功，用户ID: ${socket.userId}`);

      // 存储在线用户
      if (onlineUsers.has(socket.userId)) {
        const oldSocket = onlineUsers.get(socket.userId);
        oldSocket.emit("login-kick", "你的账号在其他设备登录");
        oldSocket.disconnect();
      }
      onlineUsers.set(socket.userId, socket);

      // 通知认证成功
      socket.emit("auth-success", {
        userId: socket.userId,
        username: socket.userName,
        onlineCount: onlineUsers.size,
      });

      // 监听消息事件 - 适配原生WebSocket消息格式
      socket.on("message", (rawMessage) => {
        try {
          // 解析消息内容
          const message = JSON.parse(rawMessage);
          const { event, data } = message;
          
          // 根据事件类型处理不同的消息
          if (event === 'ping-test') {
            // 心跳处理
            socket.emit("pong-test", { timestamp: Date.now() });
          } else if (event === 'send-message') {
            // 处理发送消息
            handleSendMessage(socket, data);
          } else if (event === 'call-invite') {
            // 处理通话邀请
            handleCallInvite(socket, data);
          } else if (event === 'call-answer') {
            // 处理通话应答
            handleCallAnswer(socket, data);
          } else if (event === 'ice-candidate') {
            // 处理ICE候选
            handleIceCandidate(socket, data);
          } else if (event === 'call-hangup') {
            // 处理挂断通话
            handleCallHangup(socket, data);
          }
        } catch (error) {
          console.error("处理消息失败:", error);
        }
      });

      // 监听断开连接事件
      socket.on("disconnect", async (reason) => {
        if (socket.userId) {
          onlineUsers.delete(socket.userId);
          console.log(
            `用户离线：userId=${socket.userId}，原因=${reason}，当前在线数=${onlineUsers.size}`
          );
          
          // 通知其他用户该用户离线
          socket.broadcast.emit("user-status-change", {
            user_id: socket.userId,
            is_online: false,
            timestamp: new Date().toISOString(),
          });
        }
        console.log(`用户断开连接：socketID=${socket.id}，原因=${reason}`);
      });

    } catch (error) {
      console.log("Token验证失败：", error.message, "，错误类型：", error.name);
      // 发送具体的错误信息给客户端
      socket.emit("auth-error", {
        message: error.message,
        errorType: error.name,
        tokenExpired: error.name === "TokenExpiredError",
      });
      // 延迟断开连接，给客户端时间接收错误信息
      setTimeout(() => {
        socket.disconnect();
      }, 100);
      return;
    }
  });
}

// 消息处理函数
function handleSendMessage(socket, data) {
  const { receiverId, content, messageType = "text" } = data;
  console.log(
    `接收到消息: 从 ${socket.userId} 到 ${receiverId}: ${content}`
  );

  // 创建消息对象
  const messageData = {
    sender_id: socket.userId,
    sender_name: socket.userName,
    receiver_id: receiverId,
    content: content,
    message_type: messageType,
    timestamp: new Date().toISOString(),
  };

  // 发送消息给接收者
  const isSent = sendToUser(receiverId, "new-message", messageData);

  // 通知发送者消息状态
  socket.emit("message-status", {
    messageId: Date.now(), // 简单生成一个临时ID
    status: isSent ? "sent" : "delivered", // 如果在线就是已发送，离线就是已投递
    receiverId: receiverId,
  });
}

// 通话相关函数
function handleCallInvite(socket, data) {
  const { targetUserId, callType } = data; // callType: 'audio'/'video'
  // 检查目标用户是否在线
  const targetSocket = onlineUsers.get(targetUserId);
  if (!targetSocket) {
    socket.emit("call-error", "对方用户不在线");
    return;
  }
  // 向目标用户发送邀请（携带发起方ID、通话类型）
  targetSocket.emit("call-receive", {
    fromUserId: socket.userId,
    callType: callType || "audio",
  });
  // 触发目标用户震动提醒
  targetSocket.emit("call-vibrate");
  console.log(
    `通话邀请：${socket.userId} → ${targetUserId}，类型=${callType}`
  );
}

function handleCallAnswer(socket, data) {
  const { targetUserId, isAccept } = data;
  const targetSocket = onlineUsers.get(targetUserId);
  if (!targetSocket) {
    socket.emit("call-error", "对方已离线");
    return;
  }
  // 通知发起方应答结果
  targetSocket.emit("call-answer-res", {
    fromUserId: socket.userId,
    isAccept: isAccept || false,
  });
  console.log(
    `通话应答：${socket.userId} 对 ${targetUserId} 的邀请，结果=${
      isAccept ? "同意" : "拒绝"
    }`
  );
}

function handleIceCandidate(socket, data) {
  const { targetUserId, candidate } = data;
  const targetSocket = onlineUsers.get(targetUserId);
  if (!targetSocket || !candidate) return;
  // 转发ICE候选给目标用户
  targetSocket.emit("ice-candidate", {
    fromUserId: socket.userId,
    candidate: candidate,
  });
}

function handleCallHangup(socket, targetUserId) {
  const targetSocket = onlineUsers.get(targetUserId);
  if (targetSocket) {
    targetSocket.emit("call-hangup", socket.userId);
    console.log(
      `通话挂断：${socket.userId} 挂断了与 ${targetUserId} 的通话`
    );
  }
  // 清理当前用户的通话状态
  socket.emit("call-hangup-self");
}

// 发送消息给特定用户
function sendToUser(userId, event, data) {
  const userIdStr = userId.toString(); // 确保ID是字符串格式
  const userSocket = onlineUsers.get(userIdStr);
  
  console.log(`尝试发送消息到用户 ${userIdStr}，事件：${event}`);
  
  if (userSocket) {
    try {
      userSocket.emit(event, data);
      console.log(`消息发送成功：用户 ${userIdStr}，事件：${event}`);
      return true;
    } catch (error) {
      console.error(`发送消息到用户${userIdStr}失败:`, error);
      return false;
    }
  } else {
    console.warn(`用户 ${userIdStr} 不在在线用户列表中`);
    return false;
  }
}

// 其他辅助函数保持不变
function getIO() { return ioInstance; }
function getOnlineCount() { return onlineUsers.size; }
function getUserSocket(userId) { return onlineUsers.get(userId); }
function isUserOnline(userId) { return onlineUsers.has(userId.toString()); }
function getOnlineUsers() {
  const users = [];
  onlineUsers.forEach((socket, userId) => {
    users.push({
      user_id: userId,
      user_name: socket.userName,
      online_since: new Date().toISOString(),
    });
  });
  return users;
}

// 发送好友关系更新通知
function notifyFriendshipUpdate(userId, updateType, friendInfo) {
  const event = 'friendship-update';
  const data = {
    type: updateType, // 'added', 'removed', 'updated'
    friend: friendInfo,
    timestamp: new Date().toISOString()
  };
  
  console.log(`向用户 ${userId} 发送好友关系更新通知:`, data);
  return sendToUser(userId, event, data);
}

// 统一使用module.exports导出所有函数
module.exports = {
  initSocketIO,
  getIO,
  getOnlineCount,
  getUserSocket,
  sendToUser,
  isUserOnline,
  getOnlineUsers,
  notifyFriendshipUpdate
};
